package com.idlecode.component;

import com.idlecode.statics.TemplateInfoStatic;

import javax.swing.*;
import javax.swing.plaf.basic.BasicComboBoxUI;
import javax.swing.plaf.basic.BasicComboPopup;
import javax.swing.plaf.basic.ComboPopup;
import java.awt.*;
import java.awt.event.MouseAdapter;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.util.ArrayList;
import java.util.List;

/**
 * @program: IdleCode
 * @description
 * @author: rongjuwei
 * @create: 2024-04-25 11:49
 **/
public class MultiSelectComboBox extends JComboBox<MultiSelectComboBox.CheckBoxListItem> {
    private List<CheckBoxListItem> selectedItems;
    private MultiSelectListCellRenderer renderer;

    public MultiSelectComboBox(List<String> items) {
        renderer = new MultiSelectListCellRenderer();
        setRenderer(renderer);
        setEditable(true);
        setMaximumRowCount(Integer.MAX_VALUE);
        setUI(new BasicComboBoxUI() {
            @Override
            protected ComboPopup createPopup() {
                return new MultiSelectComboBoxPopup(MultiSelectComboBox.this);
            }
        });

        selectedItems = new ArrayList<>();

        for (String item : items) {
            addItem(new CheckBoxListItem(item));
        }

        getEditor().getEditorComponent().addMouseListener(new MouseAdapter() {
            @Override
            public void mouseClicked(MouseEvent e) {
                if (SwingUtilities.isRightMouseButton(e)) {
                    showPopup();
                }
            }
        });
        // 设置提示文本
        updateComboBoxText();
    }

    public void updateComboBoxText() {
        // 构造显示文本
        StringBuilder newText = new StringBuilder();
        for (CheckBoxListItem item : selectedItems) {
            newText.append(item.getText()).append(", ");
        }
        if (newText.length() > 0) {
            newText.delete(newText.length() - 2, newText.length());
        }

        // 设置下拉框的文本为构造的显示文本
        getEditor().setItem(TemplateInfoStatic.getNames().size() == selectedItems.size() ? "全选" : "已选择" + selectedItems.size() + "项");
        // 更新提示文本
        setToolTipText(newText.toString());
    }

    public List<String> getSelectedItems() {
        List<String> selectedItemsText = new ArrayList<>();
        for (CheckBoxListItem item : selectedItems) {
            selectedItemsText.add(item.getText());
        }
        return selectedItemsText;
    }

    public void setSelectedItems(List<String> items) {
        for (CheckBoxListItem selectedItem : selectedItems) {
            selectedItem.setSelected(false);
        }
        // 清空已选中的选项
        selectedItems.clear();

        // 根据提供的选项列表选中对应的选项
        for (String item : items) {
            for (int i = 0; i < getItemCount(); i++) {
                CheckBoxListItem listItem = getItemAt(i);
                if (listItem.getText().equals(item)) {
                    listItem.setSelected(true);
                    selectedItems.add(listItem);
                    break;
                }
            }
        }

        // 更新显示文本和提示文本
        updateComboBoxText();
    }

    public void showPopup() {
        MultiSelectComboBoxPopup popup = (MultiSelectComboBoxPopup) getUI().getAccessibleChild(this, 0);
        popup.show();
    }

    public static class CheckBoxListItem {
        private String text;
        private boolean isSelected;

        public CheckBoxListItem(String text) {
            this.text = text;
        }

        public String getText() {
            return text;
        }

        public boolean isSelected() {
            return isSelected;
        }

        public void setSelected(boolean selected) {
            isSelected = selected;
        }

        @Override
        public String toString() {
            return text;
        }
    }

    private class MultiSelectComboBoxPopup extends BasicComboPopup {
        private static final long serialVersionUID = 1L;

        public MultiSelectComboBoxPopup(JComboBox comboBox) {
            super(comboBox);
        }

        @Override
        public void show() {
            super.show();
        }

        @Override
        protected JScrollPane createScroller() {
            JScrollPane scroller = super.createScroller();
            scroller.setHorizontalScrollBarPolicy(ScrollPaneConstants.HORIZONTAL_SCROLLBAR_NEVER);
            return scroller;
        }

        @Override
        protected MouseListener createListMouseListener() {
            return new MouseAdapter() {
                @Override
                public void mouseClicked(MouseEvent e) {
                    int index = list.locationToIndex(e.getPoint());
                    CheckBoxListItem item = (CheckBoxListItem) list.getModel().getElementAt(index);
                    item.setSelected(!item.isSelected());
                    if (item.isSelected()) {
                        selectedItems.add(item);
                    } else {
                        selectedItems.remove(item);
                    }
                    updateComboBoxText();
                    list.repaint();

                }
            };
        }
    }

    private class MultiSelectListCellRenderer extends JCheckBox implements ListCellRenderer<CheckBoxListItem> {
        private static final long serialVersionUID = 1L;

        @Override
        public Component getListCellRendererComponent(JList<? extends CheckBoxListItem> list, CheckBoxListItem value, int index,
                                                      boolean isSelected, boolean cellHasFocus) {
            setText(value.getText());
            setSelected(value.isSelected());
            return this;
        }
    }
}
